import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author gwqin
 * @description
 * @date 2023-08-28 10:05
 */
public class MakeDate {

    private static final Connection CONNECTION;

    private static final Map<String, Integer> TABLE_DATA_TARGET_COUNT = new HashMap<>();

    static {
        try {
            CONNECTION = getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }


        // TODO 配置各个表的目标数据量
        TABLE_DATA_TARGET_COUNT.put("bfsp_income_by_product", 200);
    }

    public static void main(String[] args) throws SQLException {
        List<String> tableNames = getTableNames("db_wsp_fp");
        int batchSize = 100;
        for (String tableName : tableNames) {
            if (TABLE_DATA_TARGET_COUNT.containsKey(tableName)) {
                insertData(tableName, batchSize);
            }
        }
    }

    private static void insertData(String tableName, int batch) throws SQLException {
        int makeDataCount = TABLE_DATA_TARGET_COUNT.get(tableName) - queryCurrentCount(tableName);
        Map<String, Object> oneData = getOneData(tableName);

        List<String> columnNames = new ArrayList<>();
        List<String> columnTypes = new ArrayList<>();
        List<String> primaryKeys = new ArrayList<>();
        getTableMeta(tableName, columnNames, columnTypes, primaryKeys);
        if (columnNames.contains("unionid")) {
            primaryKeys.add("unionid");
        }
        Map<String, Object> primaryKeysMax = getPrimaryKeysMax(tableName, primaryKeys);

        int index = 0;
        while (index <= makeDataCount) {
            System.out.println("正在造数据入库，当前表：" + tableName + "，还剩数据量：" + (makeDataCount - index));
            StringBuilder sb = new StringBuilder("insert into ").append(tableName).append(" (");
            for (int i = 0; i < columnNames.size(); i++) {
                if (i != 0) {
                    sb.append(", ");
                }
                String columnName = columnNames.get(i);
                sb.append(columnName);
            }

            sb.append(") VALUES ");

            for (int i = 0; i < batch; i++) {
                index++;
                sb.append("(");
                for (int j = 0; j < columnNames.size(); j++) {
                    String columnName = columnNames.get(j);
                    Object value = primaryKeysMax.get(columnName);
                    if (value != null) {
                        if (value instanceof Number) {
                            value = ((Number)value).intValue() + index;
                        } else {
                            value = value.toString() + index;
                        }
                    } else {
                        value = oneData.get(columnName);
                    }

                    sb.append("'").append(value).append("'");

                    if (j != columnNames.size() - 1) {
                        sb.append(",");
                    }
                }
                sb.append(")");
                if (i != batch - 1) {
                    sb.append(",");
                }
            }

            String sql = sb.toString();
            System.out.println(sql);
            CONNECTION.createStatement().execute(sql);
        }
    }

    private static Map<String, Object> getOneData(String tableName) throws SQLException {
        String select = "select * from " + tableName + " limit 1";
        ResultSet resultSet = CONNECTION.createStatement().executeQuery(select);
        HashMap<String, Object> resultMap = new HashMap<>();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();

        while (resultSet.next()) {
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                Object value = resultSet.getObject(i);
                resultMap.put(columnName, value);
            }
        }
        resultSet.close();
        return resultMap;
    }

    private static Map<String, Object> getPrimaryKeysMax(String tableName, List<String> primaryKeys) throws SQLException {
        StringBuilder sb = new StringBuilder("select ");
        for (int i = 0; i < primaryKeys.size(); i++) {
            sb.append("max(").append(primaryKeys.get(i)).append(")").append(" as ").append(primaryKeys.get(i));
            if (i != primaryKeys.size() - 1) {
                sb.append(",");
            }
        }
        sb.append(" from ").append(tableName);
        ResultSet resultSet = CONNECTION.createStatement().executeQuery(sb.toString());
        HashMap<String, Object> resultMap = new HashMap<>();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();

        while (resultSet.next()) {
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                Object value = resultSet.getObject(i);
                resultMap.put(columnName, value);
            }
        }
        resultSet.close();
        return resultMap;
    }

    /**
     * 获取当前表的数据量
     *
     * @param tableName
     * @return
     * @throws SQLException
     */
    private static int queryCurrentCount(String tableName) throws SQLException {
        String sql = "select count(1) from " + tableName;
        Statement statement = CONNECTION.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        int count = 0;
        if (resultSet.next()) {
            count = resultSet.getInt(1);
        }
        resultSet.close();
        statement.close();
        return count;
    }

    private static void getTableMeta(String tableName, List<String> columnNames, List<String> columnTypes, List<String> primaryKeys) throws SQLException {
        DatabaseMetaData metaData = CONNECTION.getMetaData();
        ResultSet rs = metaData.getColumns(null, null, tableName, null);

        // 遍历结果集，获取字段名和类型
        while (rs.next()) {
            String columnName = rs.getString("COLUMN_NAME");
            String columnType = rs.getString("TYPE_NAME");

            columnNames.add(columnName);
            columnTypes.add(columnType);
        }

        // 获取表的唯一键信息
        ResultSet pk = metaData.getPrimaryKeys(null, null, tableName);

        // 遍历结果集，获取唯一键字段名
        while (pk.next()) {
            String primaryKeyColumnName = pk.getString("COLUMN_NAME");
            primaryKeys.add(primaryKeyColumnName);
        }

        rs.close();
        pk.close();
    }

    private static List<String> getTableNames(String dbName) throws SQLException {
        DatabaseMetaData metaData = CONNECTION.getMetaData();
        ResultSet catalogs = metaData.getCatalogs();
        // 遍历数据库，并获取每个数据库下的表
        List<String> tableNames = new ArrayList<>();
        while (catalogs.next()) {
            String catalogName = catalogs.getString(1);
            if (!dbName.equals(catalogName)) {
                continue;
            }
            // 获取指定数据库下的表
            ResultSet tables = metaData.getTables(catalogName, null, null, new String[]{"TABLE"});
            while (tables.next()) {
                String tableName = tables.getString("TABLE_NAME");
                tableNames.add(tableName);
            }

            tables.close();
        }

        catalogs.close();
        return tableNames;
    }

    private static Connection getConnection() throws SQLException {
        String url = "jdbc:mysql://172.17.7.139:3306/db_wsp_fp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false";
        String username = "root";
        String password = "Beta@0727";

        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }
}
